package com.hwadee.teachingprocessmanagementsystem.dao;

import org.apache.ibatis.annotations.*;
import org.apache.ibatis.jdbc.SQL;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

import static com.hwadee.teachingprocessmanagementsystem.service.base.impl.TableServiceImpl.camelToSnakeCase;

/**
 * @Description:
 * @Author: Jukomu
 * @Package: com.hwadee.teachingprocessmanagementsystem.dao
 * @Project: TeachingProcessManagementSystem
 * @name: TableDao
 * @Date: 2024/7/17-23:37
 * @Filename: TableDao
 */
@Mapper
public interface TableDao<T> {
    @Select("SHOW TABLES")
    List<String> getAllTable();

    @SelectProvider(type = SqlProvider.class, method = "selectTableDetail")
    List<Map<String, Object>> getTableDetail(@Param("tableName") String tableName);

    @UpdateProvider(type = SqlProvider.class, method = "updateTable")
    int updateTable(@Param("tableName") String tableName, @Param("entity") T entity);

    @DeleteProvider(type = SqlProvider.class, method = "deleteTable")
    int deleteTable(@Param("tableName") String tableName, @Param("entity") T entity);

    @InsertProvider(type = SqlProvider.class, method = "createTable")
    int createTable(@Param("tableName") String tableName, @Param("entity") T entity);

    class SqlProvider {
        public String selectTableDetail(@Param("tableName") String tableName) {
            return "SELECT * FROM " + tableName;
        }

        public String updateTable(@Param("tableName") String tableName, @Param("entity") Object entity) {
            SQL sql = new SQL().UPDATE(tableName);

            try {
                Field[] fields = entity.getClass().getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    Object value = field.get(entity);
                    if (value != null) {
                        sql.SET(camelToSnakeCase(field.getName()) + " = #{entity." + field.getName() + "}");
                    }
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Error accessing entity fields", e);
            }

            // You need to specify a WHERE clause to avoid updating all rows
            sql.WHERE("id = #{entity.id}"); // Assuming 'id' is the primary key

            return sql.toString();
        }

        public String deleteTable(@Param("tableName") String tableName, @Param("entity") Object entity) {
            SQL sql = new SQL().DELETE_FROM(tableName);

            try {
                Field idField = entity.getClass().getDeclaredField("id");
                idField.setAccessible(true);
                Object idValue = idField.get(entity);
                sql.WHERE("id = #{entity.id}");
            } catch (NoSuchFieldException | IllegalAccessException e) {
                throw new RuntimeException("Error accessing entity ID field", e);
            }
            return sql.toString();
        }

        public String createTable(@Param("tableName") String tableName, @Param("entity") Object entity) {
            SQL sql = new SQL().INSERT_INTO(tableName);

            try {
                Field[] fields = entity.getClass().getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    Object value = field.get(entity);
                    if (value != null) {
                        sql.VALUES(camelToSnakeCase(field.getName()), "#{entity." + field.getName() + "}");
                    }
                }
            } catch (IllegalAccessException e) {
                throw new RuntimeException("Error accessing entity fields", e);
            }

            return sql.toString();
        }
    }
}
